package com.css.openapi.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.crypto.SecureUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.css.common.core.constant.Result;
import com.css.common.core.constant.ReturnCode;
import com.css.common.core.exception.ServiceException;
import com.css.common.core.session.SessionUtils;
import com.css.common.core.utils.BaseUtil;
import com.css.common.core.utils.DateUtils;
import com.css.common.core.utils.GyUtils;
import com.css.openapi.BO.BdKpyVO;
import com.css.openapi.BO.KpyxxVO;
import com.css.openapi.BO.QyKpySqBO;
import com.css.openapi.BO.lypt.BdKpyReq;
import com.css.openapi.BO.lypt.BdKpyResponse;
import com.css.openapi.BO.lypt.QueryKpyRepsonse;
import com.css.openapi.BO.lypt.QueryShkpyRequest;
import com.css.openapi.entity.QyKpySq;
import com.css.openapi.entity.QyYwlx;
import com.css.openapi.entity.YhShbdkpyDO;
import com.css.openapi.feign.ZfjkpPtCommonClient;
import com.css.openapi.mapper.QyKpySqMapper;
import com.css.openapi.mapper.QyYwlxMapper;
import com.css.openapi.service.IQyKpySqService;
import com.css.openapi.service.IQyYwlxService;
import com.css.openapi.service.YhShbdkpyService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * <p>
 * 开票员授权明细表 服务实现类
 * </p>
 *
 * @author qinxb
 * @since 2025-01-20 10:18:37
 */
@Service
@Slf4j
public class QyKpySqServiceImpl extends ServiceImpl<QyKpySqMapper, QyKpySq> implements IQyKpySqService {
    @Resource
    private IQyYwlxService ywlxService;
    @Resource
    private QyYwlxMapper qyYwlxMapper;
    @Resource
    private ZfjkpPtCommonClient zfjkpPtCommonClient;
    @Resource
    private YhShbdkpyService yhShbdkpyService;

    @Override
    public List<QyKpySqBO> queryKpy(String shbdbh) {
        if (GyUtils.isNull(shbdbh)) throw new ServiceException("入参shbdbh不能为空");
        QyYwlx qyYwlx = qyYwlxMapper.getQyBdzt(shbdbh);
        if (Objects.isNull(qyYwlx)) {
            throw new ServiceException("查询商户绑定编号为空，未进行商户绑定申请或未绑定成功。");
        }
        //查询支付即开票平台信息
        QueryShkpyRequest reqKpy=new QueryShkpyRequest();
        reqKpy.setShbdbh(shbdbh);
        QueryKpyRepsonse kpyRep = zfjkpPtCommonClient.queryKpy(reqKpy);
        if (!Objects.equals("0", kpyRep.getCode())) throw new ServiceException(kpyRep.getMsg());
        List<QyKpySq> kpysq = this.lambdaQuery().eq(QyKpySq::getShbdbh, shbdbh).eq(QyKpySq::getScbj, "0").list();
        List<QyKpySqBO> kpyxxVOList = kpyRep.getKpyxx();
        //保存开票员信息
        onKpyData(kpysq, kpyxxVOList, qyYwlx);
        return BeanUtil.copyToList(kpyRep.getKpyxx(), QyKpySqBO.class);
    }

    @Override
    public Result<BdKpyVO> bdKpy(BdKpyReq param) {
        log.info("绑定开票员参数：{}", JSON.toJSONString(param));
        //校验商户绑定编号是否合法
        QyYwlx qyYwlx = ywlxService.lambdaQuery().eq(QyYwlx::getShbdbh, param.getShbdbh()).eq(QyYwlx::getBdzt, "00").last(" limit 1").one();
        if (Objects.isNull(qyYwlx)) {
            throw new ServiceException("查询商户绑定编号为空，未进行商户绑定申请或未绑定成功。");
        }
        if (GyUtils.isNull(param.getKpyid()) && GyUtils.isNull(param.getKpyxm()) && GyUtils.isNull(param.getJmsfzjhm())) {
            throw new ServiceException("开票员id,开票员姓名，居民身份证号码不能同时为空。");
        }
        if (GyUtils.isNotNull(param.getKpyid())) {
            //查询开票员
            QyKpySq kpysq = this.lambdaQuery().eq(QyKpySq::getKpyid, param.getKpyid()).one();
            if (Objects.isNull(kpysq)) throw new ServiceException("通过开票员id:" + param.getKpyid() + "，未查询到开票员信息。");
            param.setJmsfzjhm(kpysq.getKpysfzjhm());
            param.setKpyxm(kpysq.getKpyxm());
            log.info("绑定开票员通过kpyid查询数据：姓名{}，证件号：{}", param.getKpyxm(), param.getJmsfzjhm());
        } else {
            QyKpySq kpysq = this.lambdaQuery().eq(QyKpySq::getShbdbh, param.getShbdbh())
                    .eq(QyKpySq::getKpysfzjhm, param.getJmsfzjhm()).one();
            if (Objects.isNull(kpysq)) throw new ServiceException("通过开票员身份证号码:" + param.getJmsfzjhm() + "，未查询到开票员信息。");
        }
        //校验商户是否已绑定该开票员
        final YhShbdkpyDO yhShbdkpyDO = this.yhShbdkpyService.lambdaQuery().select(YhShbdkpyDO::getKpybdbh)
                .eq(YhShbdkpyDO::getShbdbh, param.getShbdbh())
                .eq(YhShbdkpyDO::getKpyxm, param.getKpyxm())
                .eq(YhShbdkpyDO::getKpyzjhm, param.getJmsfzjhm())
                .last("limit 1")
                .one();
        if (GyUtils.isNotNull(yhShbdkpyDO)) return Result.error(-1, "该商户已绑定过该开票员。");
        //调用联用平台保存开票员
        BdKpyResponse bdKpyResponse = zfjkpPtCommonClient.bdKpy(param);
        if (!Objects.equals("0", bdKpyResponse.getCode())) throw new ServiceException(bdKpyResponse.getMsg());
        //本地保存绑定开票员
        final YhShbdkpyDO entity = new YhShbdkpyDO();
        entity.setKpybdbh(bdKpyResponse.getKpybdbh());
        entity.setShbdbh(param.getShbdbh());
        entity.setKpyxm(param.getKpyxm());
        entity.setKpyzjhm(param.getJmsfzjhm());
        entity.setShsh(qyYwlx.getShsh());
        entity.setShmc(qyYwlx.getShmc());
        entity.setScbj("0");
        entity.setKpyzjlxDm("201");
        entity.setCjr(qyYwlx.getShsh());
        entity.setCjsj(LocalDateTime.now());
        entity.setXgsj(LocalDateTime.now());
        final BdKpyVO bdKpyVO = new BdKpyVO();
        bdKpyVO.setKpybdbh(bdKpyResponse.getKpybdbh());
        yhShbdkpyService.save(entity);
        return Result.ok(bdKpyVO);
    }

    private void onKpyData(List<QyKpySq> kpysqList, List<QyKpySqBO> lqKpyList, QyYwlx qyYwlx) {
        if (Objects.isNull(kpysqList)) {
            List<QyKpySq> kpySqList = new ArrayList<>();
            //本地开票员授权为空，保存乐企开票数据
            for (QyKpySqBO kpyxxVO : lqKpyList) {
                QyKpySq kpySq = new QyKpySq();
                setBean(kpySq, kpysqList, kpyxxVO, qyYwlx);
            }
            log.info("添加开票员{}", kpySqList.size());
            boolean idAdd = this.saveBatch(kpySqList);
        } else {
            List<QyKpySq> updateKpy = new ArrayList<>();
            List<QyKpySq> addKpy = new ArrayList<>();
            //根据乐企返回的开票人更新本地开票人
            for (QyKpySqBO kpyxxVO : lqKpyList) {
                QyKpySq bdKpy = null;
                for (QyKpySq kpySq : kpysqList) {
                    if (kpyxxVO.getKpysfzjhm().equals(kpySq.getKpysfzjhm())) {
                        bdKpy = kpySq;
                        break;
                    }
                }
                if (!Objects.isNull(bdKpy)) {
                    if (GyUtils.isNotNull(kpyxxVO.getYqsj())) {
                        bdKpy.setYqsj(kpyxxVO.getYqsj());
                    }
                    if (GyUtils.isNotNull(kpyxxVO.getQrsj())) {
                        bdKpy.setQrsj(kpyxxVO.getQrsj());
                    }
                    if (GyUtils.isNotNull(kpyxxVO.getJcsj())) {
                        bdKpy.setJcsj(kpyxxVO.getJcsj());
                    }
                    bdKpy.setDjzt(kpyxxVO.getDjzt());
                    bdKpy.setXgsj(LocalDateTime.now());
                    updateKpy.add(bdKpy);
                } else {
                    bdKpy = new QyKpySq();
                    setBean(bdKpy, addKpy, kpyxxVO, qyYwlx);
                }
            }
            updateKpy.addAll(addKpy);
            log.info("添加或更新开票{}", updateKpy.size());
            this.saveOrUpdateBatch(updateKpy);
        }
    }

    private void setBean(QyKpySq kpySq, List<QyKpySq> kpySqList, QyKpySqBO kpyxxVO, QyYwlx qyYwlx) {
        kpySq.setUuid(IdUtil.fastSimpleUUID());
        kpySq.setKpyid(kpyxxVO.getKpyid());
        kpySq.setKpyxm(kpyxxVO.getKpyxm());
        kpySq.setKpysfzjhm(kpyxxVO.getKpysfzjhm());
        kpySq.setKpyzjlx(kpyxxVO.getKpyzjlx());
        kpySq.setDjzt(kpyxxVO.getDjzt());
        kpySq.setShbdbh(qyYwlx.getShbdbh());
        kpySq.setCjr(SessionUtils.getAppid());
        kpySq.setCjsj(LocalDateTime.now());
        if (GyUtils.isNotNull(kpyxxVO.getYqsj())) {
            kpySq.setYqsj(kpyxxVO.getYqsj());
        }
        if (GyUtils.isNotNull(kpyxxVO.getQrsj())) {
            kpySq.setQrsj(kpyxxVO.getQrsj());
        }
        if (GyUtils.isNotNull(kpyxxVO.getJcsj())) {
            kpySq.setJcsj(kpyxxVO.getJcsj());
        }
        kpySqList.add(kpySq);
    }


    @Override
    public void jbKpy(Map<String,String> req) {
        final String shbdbh = req.get("shbdbh");
        final String kpybdbh = req.get("kpybdbh");
        if (BaseUtil.isNull(shbdbh) || BaseUtil.isNull(kpybdbh)) throw new ServiceException(-1, "商户绑定编号或开票员绑定编号不能为空");

        //调用开发平台解绑定
        ReturnCode result =  zfjkpPtCommonClient.jbKpy(req);
        if (!"0".equals(result.getCode())) throw new ServiceException(result.getMsg());

        yhShbdkpyService.lambdaUpdate().eq(YhShbdkpyDO::getShbdbh, shbdbh).eq(YhShbdkpyDO::getKpybdbh, kpybdbh)
                .set(YhShbdkpyDO::getScbj, "1").set(YhShbdkpyDO::getCjr, SessionUtils.getAppid())
                .set(YhShbdkpyDO::getXgsj, LocalDateTime.now()).update();
    }

}
